import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
//碰撞
import { Octree } from 'three/examples/jsm/math/Octree.js'
import { Capsule } from 'three/examples/jsm/math/Capsule.js'

export const mixins = {
  data() {
    return {
      player: '',
      keyStates:{
    // 使用W、A、S、D按键来控制前、后、左、右运动
    // false表示没有按下，true表示按下状态
    W: false,
    A: false,
    S: false,
    D: false,
    Space:false,
    leftMouseBtn: false,
      },
      playerActionState :{
    forward: 0,
    turn: 0
      },
       vector1:new THREE.Vector3(),
      vector2:new THREE.Vector3(),
      vector3: new THREE.Vector3(),
    GRAVITY:30
    };
   
        
    
  },

  created() {},
    mounted() { },
    beforeDestroy() {
    window.removeEventListener('wheel', this.handleMouseWheel)
    clearTimeout()
    try {
      this.scene.clear()
      this.render.dispose()
      this.render.forceContextLoss()
      this.render.content = null
      // cancelAnimationFrame(animationID) // 去除animationFrame
      const gl = this.render.domElement.getContext('webgl')
      gl && gl.getExtension('WEBGL_lose_context').loseContext()
    } catch (e) {
      console.log(e)
    }
    },
      computed: {
    getPosition() {
      //根据返回的位置信息计算物品提示小标位
      let maincontWidth = this.$el.offsetWidth
      let maincontHeight = this.$el.offsetHeight
      let leftPercentage = ((this.tipPosition.x + 25) / maincontWidth) * 100
      let topPercentage = ((this.tipPosition.y - 30) / maincontHeight) * 100
      return 'left:' + leftPercentage + '%;top:' + topPercentage + '%;'
    }
  },
    methods: {
            //初始化
    init() {
      window.addEventListener('resize', this.onWindowResize, false)
      this.initSence()
      this.initCeremar()
     
      this.initPoint()
      this.initFile()
      this.initFileS(0)
        this.initLight()
        this.initbot()
        this.initCotronl()
        this.initMass()
         this.initRenderer()
      this.raycaster = new THREE.Raycaster() // 设置光线拾取
      this.clock = new THREE.Clock()
      this.mouse = new THREE.Vector2()
        },
            //初始化相机
    initCeremar() {
      const camera = new THREE.PerspectiveCamera(
        50,
        window.innerWidth / window.innerHeight,
        0.01,
        10000
      )
      camera.position.set(0, 1.6, -5.5);
    camera.lookAt(0, 1.6, 0);//对着人身上某个点
      // camera.position.set(
      //   this.cameraOriginal[0],
      //   this.cameraOriginal[1],
      //   this.cameraOriginal[2]
      // )
      this.camera = camera
    },
    //初始化场景
    initSence() {
      this.scene = new THREE.Scene()
    },
    //初始化渲染器
    initRenderer() {
      this.render = new THREE.WebGLRenderer({
        antialias: true,
        logarithmicDepthBuffer: true
      })
      this.render.setPixelRatio(window.devicePixelRatio)
      this.render.outputEncoding = THREE.sRGBEncoding
      this.render.setSize(window.innerWidth, window.innerHeight)
      this.render.shadowMap.enabled = true
window.addEventListener('resize', this.onWindowResize) //监听窗口变化
      this.$el.appendChild(this.render.domElement)
    },
    //初始化控制器
      initCotronl() {
      this.ForwardHoldTimeClock = new THREE.Clock()
 this.ForwardHoldTimeClock.autoStart = false
 

      this.mouse = new THREE.Vector2() //获取鼠标 位置二维坐标信息
      document.body.addEventListener('mousemove', this.onDocumentMouseMove)
      document.body.addEventListener('mousedown', this.onDocumentMouseDown)
      this.$el.addEventListener('mouseup', this.onDocumentMouseUp)
      // 当某个键盘按下设置对应属性设置为true
    document.addEventListener('keydown', (event) => {
        if (event.code === 'KeyW') {
            this.keyStates.W = true; this.playerActionState.forward = 1;
            if(! this.keyW){ // keydown事件在按下按键不松时会持续激活，因此需进行状态控制，避免计时器重复计时
                 this.ForwardHoldTimeClock.start()
                 this.keyW = true
            }
            // console.log(ForwardHoldTimeClock.getElapsedTime())
        }
        if (event.code === 'KeyA') { this.keyStates.A = true; this.playerActionState.turn = -1}
        if (event.code === 'KeyS') { this.keyStates.S = true; this.playerActionState.forward = -1}
        if (event.code === 'KeyD') { this.keyStates.D = true; this.playerActionState.turn = 1}
        if (event.code === 'Space') { this.keyStates.Space = true;}
    });
       document.addEventListener('keyup', (event) => {
        if (event.code === 'KeyW') {
            this.keyW = false
            this.keyStates.W = false;this.playerActionState.forward = 0;
            this.ForwardHoldTimeClock.stop()
            this.ForwardHoldTimeClock.elapsedTime = 0
        }
        if (event.code === 'KeyA') {this.keyStates.A = false;this.playerActionState.turn = 0}
        if (event.code === 'KeyS') {this.keyStates.S = false;this.playerActionState.forward = 0}
        if (event.code === 'KeyD') {this.keyStates.D = false;this.playerActionState.turn = 0}
        if (event.code === 'Space') this.keyStates.Space = false

        // 保持按键打断前的状态
        // console.log(keyStates)
        this.playerActionState.forward = this.keyStates.W == true ? 1 : this.playerActionState.forward
        this.playerActionState.turn = this.keyStates.A == true? -1 : this.playerActionState.turn
        this.playerActionState.forward = this.keyStates.S == true? -1 : this.playerActionState.forward
        this.playerActionState.turn = this.keyStates.D == true? 1 : this.playerActionState.turn
        // console.log(playerActionState)

    });
    // 鼠标按下时锁定禁用鼠标指针
    document.addEventListener('mousedown', (e) => {
        // document.body.requestPointerLock()
        if(e.button == 0){
            // 鼠标左键被点击
            this.keyStates.leftMouseBtn = true
        }
        this.mouseTime = performance.now()
    })
    // 鼠标按键抬起，投掷小球
    document.addEventListener('mouseup', (e) => {
        // if (document.pointerLockElement !== null) throwBall();
        if(e.button == 0){
            // 鼠标左键抬起
            this.keyStates.leftMouseBtn = false
        }
    })
    // 相机视角跟随鼠标旋转
    document.body.addEventListener('mousemove', (event) => {
        // document.pointerLockElement === document.body
        // 鼠标左键拖动时移动视角
        if (this.keyStates.leftMouseBtn) {
            // console.log('mousemove')
            if(this.cameraMoveSensitivity <= 0)this.cameraMoveSensitivity = 0.001
            if(this.cameraMoveSensitivity > 1)this.cameraMoveSensitivity = 1
            this.player.rotation.y -= event.movementX / (this.cameraMoveSensitivity * 1000);
            this.camera.rotation.x -= event.movementY / (this.cameraMoveSensitivity * 1000);
        }

    });
     


      // const controls = new OrbitControls(this.camera, this.render.domElement);
      // controls.enablePan = false; //取消右键拖拽
      // controls.maxDistance = 3
      // if (this.i == 1) {
      //   controls.enabled = false;
      // }
      // controls.target.set(0, 0, 0)
      // controls.addEventListener('change', () => {
      //   this.render.render(this.scene, this.camera) //执行渲染操作
      // }) //监听鼠标、键盘事件

      // this.controls = controls;
    }, //初始化物体
    initFile() {
      let gltfloader = new GLTFLoader()
      this.app = gltfloader
      const dracoLoader = new DRACOLoader()
      // dracoLoader.setDecoderPath('/draco/')
      dracoLoader.setDecoderPath(
       window.config.VUE_GLB_Base_load
      )
      dracoLoader.preload()
      gltfloader.setDRACOLoader(dracoLoader)
      gltfloader.load(window.config.VUE_GLB_Base+ 'CTshi.glb', (gltf) => {
        this.model = gltf.scene
        var objectReItem = gltf.scene
        gltf.scene.position.set(0, 0, 0)
        if (this.worldOctree) {
          this.worldOctree.fromGraphNode(objectReItem)
        }
        gltf.scene.traverse((child) => {
          if (child.isMesh) {
            child.receiveShadow = true
            child.castShadow = true
            child.material.emissiveMap = child.material.map
            if (this.objectNames.includes(child.name)) {
              //将需要检查到的模型放到objects
              this.objects.push(child)
            }
            if (child.name == 'gxspy_zhuozi') {
              child.material.emissive = child.material.color
              child.material.emissiveMap = child.material.map
            }
            //设置模型自发光
            // child.material.emissive = child.material.color
          }
        })
        this.scene.add(gltf.scene)
        this.render.render(this.scene, this.camera)
        this.animate()
        // this.move([-21.478, 1.586, -6.088], [0, 0, 0])
        // this.initBox();
        // this.$emit('loginss')
        // this.initDragControls(this.Farray) //初始化拖拽控制器
      }),
        () => {
          // this.$emit('loginss')
        }
    },
    //根据步骤渲染物体和动画
    initFileS(index) {
      let gltfloader = new GLTFLoader()
      const dracoLoader = new DRACOLoader()
      // dracoLoader.setDecoderPath('/draco/')
      dracoLoader.setDecoderPath(
      window.config.VUE_GLB_Base_load
      )
      dracoLoader.preload()
      gltfloader.setDRACOLoader(dracoLoader)
      gltfloader.load(window.config.VUE_GLB_Base + this.dhfiles[index].url, (gltf) => {
        if (this.objectFather) {
          this.scene.remove(this.objectFather.scene)
          this.objectFather.scene.traverse((child) => {
            if (child.material) {
              child.material.dispose()
            }
            if (child.geometry) {
              child.geometry.dispose()
            }
            child = null
          })

          this.objectFather = null
        }
        gltf.scene.position.set(0, 0, 0)
        gltf.scene.traverse((child) => {
          if (child.isMesh) {
            child.castShadow = false
            child.receiveShadow = true
            child.castShadow = true
            if (this.objectNames.includes(child.name)) {
              //将需要检查到的模型放到objects
              this.objects.push(child)
            }
            // if (
            //   child.material.name == 'gxspy_csj11' ||
            //   child.material.name == 'danchuiyi_c' ||
            //   child.material.name == 'tuopan_c' ||
            //   child.material.name == 'dztp_c' ||
            //   child.material.name == 'zhipuyi_c' ||
            //   child.material.name == 'door_02' ||
            //   child.material.name == 'niezi_c'
            // ) {
            //   const textureCube = new THREE.TextureLoader().load(
            //     'https://zfatt.oss-cn-beijing.aliyuncs.com/experiment/fydw/TaiDeng_C_BaseMap.png'
            //   )
            //   textureCube.encoding = THREE.sRGBEncoding
            //   textureCube.mapping = THREE.EquirectangularReflectionMapping
            //   child.material.envMap = textureCube
            // }
            // if (
            //   child.material.name === 'BoLi_c' ||
            //   child.material.name === 'Ycls_shiguanhe3_1'
            // ) {
            //   child.material.transparent = true //材质允许透明 如果有玻璃材质时开启
            //   child.material.opacity = 0.55 //材质默认透明度
            //   child.material.shininess = 1
            //   child.material.roughness = 0.3
            //   child.material.metalness = 0.3
            // }
            child.material.emissiveMap = child.material.map
            // child.material.emissive = child.material.color
          }
        })
        this.scene.add(gltf.scene)
        this.objectFather = gltf
        this.andh = gltf.animations
        console.log('动画数据', gltf.animations)
        this.render.render(this.scene, this.camera)
        // this.initDragControls(this.Farray) //初始化拖拽控制器
      })
        },
        //初始化灯光
    initLight() {
      const ambientLight = new THREE.AmbientLight('#fff', 0.15)
      this.scene.add(ambientLight)
      const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.95)
      directionalLight1.position.set(-11.157, 11.0, 7.48)
      this.scene.add(directionalLight1)
      const light1 = new THREE.PointLight(0xffffff, 0.26, 0, 4.5)
      light1.position.set(1.963, 20, 1.311)
      this.scene.add(light1)
    },
    initPoint() {
      //初始换加载箭头指示图标
      const spriteImageLabel = (image) => {
        let textureLoader = new THREE.TextureLoader()
        const imageTexture = textureLoader.load(image)
        return imageTexture
      }
      let imgUrl = require('@/images/pointer.png')
      const spriteMap = spriteImageLabel(imgUrl)
      const spriteMaterial = new THREE.SpriteMaterial({
        map: spriteMap,
        color: 0xffffff
      })
      const sprite = new THREE.Sprite(spriteMaterial)
      sprite.scale.set(0.05, 0.05, 0.05)
      sprite.rotation.set(0, 0, Math.PI * 0.6)
      sprite.visible = false
      this.sprite = sprite
      this.scene.add(sprite)
        },
        //根据按钮播发动画
      playAction(animationName, realName) {
        console.log('播放了动画名称',animationName,'点击的物体',realName);
      this.playIng = true
      const theMixer = new THREE.AnimationMixer(this.objectFather.scene) //动画的物体
      const clip = THREE.AnimationClip.findByName(
        this.objectFather.animations,
        animationName
      ) //要播放的动画名称
      const action = theMixer.clipAction(clip)
      action.loop = THREE.LoopOnce //动画只执行一次
      action.clampWhenFinished = true //播放完成之后自动结束
      action.play()
      this.action = action
      theMixer.addEventListener('finished', () => {
        return setTimeout(() => {
          this.playIng = false
          this.$emit('clickItem', realName)
           console.log('动画播放完成')
        }, 600)
      })
      this.theMixer = theMixer
        },
     //循环渲染
      animate() {
      


           // 渲染场景
        console.log("渲染场景...")
        const clock = new THREE.Clock()
        let previousTime = 0
        const STEPS_PER_FRAME = 5;
        this.tick = () => {
          
            const deltaTime = Math.min(0.05,clock.getDelta())/ STEPS_PER_FRAME
            const elapsedTime = clock.getElapsedTime()
            const mixerUpdateDelta = elapsedTime - previousTime
            previousTime = elapsedTime

            for(let i = 0; i< STEPS_PER_FRAME; i++){
                this.gameUpdate(deltaTime)
            }
            if(this.mixer instanceof THREE.AnimationMixer){
                this.mixer.update(mixerUpdateDelta)
            }
            // // Update controls
            // this.control.update()

            // Raycast
            // pickHelper.pick(pickPosition, currentScene.scene, camera)

            // // Render
            this.renderer.render(this.scene, this.camera)

            // Call tick again on the next frame
            window.requestAnimationFrame(this.tick)
        }
        this.tick()
      //镜头移动相关
  
      // requestAnimationFrame(this.animate)

    
      // // if (this.setp == 1.2 || this.setp == 1.3) {
      // //   //  次步骤可以进行全景漫游
      // //   this.updatePlayer(deltaTime)
      // // }
    
     
      // this.render.render(this.scene, this.camera)

     
      // if (this.theMixer) {
      //   //动画渲染
      //   this.theMixer.update(this.clock.getDelta())
      // }
      // //清空原本动画事件，回调animate方法
      // if (this.outLineAnimationFrameID) {
      //   window.cancelAnimationFrame(this.outLineAnimationFrameID)
      // }
      // this.outLineAnimationFrameID = requestAnimationFrame(this.animate)
      },
    
    
     // 漫游代码
      //  添加漫游人
      //根据步骤渲染物体和动画
      controls(deltaTime) {

    // gives a bit of air control
    const speedDelta = deltaTime * (this.playerOnFloor ? 25 : 8);

    if (this.keyStates['W']) {

        this.playerVelocity.add(this.getForwardVector().multiplyScalar(speedDelta));

    }

    if (this.keyStates['S']) {

        this.playerVelocity.add(this.getForwardVector().multiplyScalar(-speedDelta));

    }

    if (this.keyStates['A']) {

        this.playerVelocity.add(this.getSideVector().multiplyScalar(-speedDelta));

    }

    if (this.keyStates['D']) {

        this.playerVelocity.add(this.getSideVector().multiplyScalar(speedDelta));

    }

    if (this.playerOnFloor) {

        if (this.keyStates['Space']) {
            this.layerVelocity.y = 15;
        }

    }

},
    initbot() {
      let gltfloader = new GLTFLoader()
   
      gltfloader.load(window.config.VUE_GLB_Base + 'Xbot.glb', (gltf) => {
       
        // gltf.scene.position.set(0, 0, 0)
       const  playerColliderHelper = this.CapsuleHelper(0.35,1.85)
        this.scene.add(gltf.scene)
        this.player = gltf.scene
        this.player.add(this.camera)
        this.player.add(playerColliderHelper)
        console.log('动画数据', gltf.animations)
        this.render.render(this.scene, this.camera)
    
      })
        },
    CapsuleHelper(R, H) {
    const group = new THREE.Group();
    const material = new THREE.MeshLambertMaterial({
        color: 0x00ffff,
        transparent: true,
        opacity: 0.5,
    });
    // 底部半球
    const geometry = new THREE.SphereGeometry(R, 25, 25, 0, 2 * Math.PI, 0, Math.PI / 2);
    geometry.rotateX(Math.PI);
    const mesh = new THREE.Mesh(geometry, material);
    mesh.position.y = R;
    group.add(mesh)
    // 顶部半球
    const geometry2 = new THREE.SphereGeometry(R, 25, 25, 0, 2 * Math.PI, 0, Math.PI / 2);
    const mesh2 = new THREE.Mesh(geometry2, material);
    mesh2.position.set(0, H - R, 0)
    group.add(mesh2)
    // 中间圆柱
    const h = H - 2 * R
    const geometry3 = new THREE.CylinderGeometry(R, R, h,32,1,true);
    geometry3.translate(0, h / 2+R,0)
    const mesh3 = new THREE.Mesh(geometry3, material);
    group.add(mesh3)
    return group;
},
    initMass() {
      this.worldOctree = new Octree()
      this.playerCollider = new Capsule(new THREE.Vector3(0, 0.35, 0), new THREE.Vector3(0, 1.5, 0), 0.35);
      // this.playerCollider = new Capsule(
      //   new THREE.Vector3(
      //     this.cameraOriginal[0],
      //     this.cameraOriginal[1],
      //     this.cameraOriginal[2]
      //   ),
      //   new THREE.Vector3(
      //     this.cameraOriginal[0],
      //     this.cameraOriginal[1] + 1,
      //     this.cameraOriginal[2]
      //   ),
      //   0.35
      // )
      this.playerVelocity = new THREE.Vector3()
      this.playerDirection = new THREE.Vector3()
    },
    playerCollisions() {
      const result = this.worldOctree.capsuleIntersect(this.playerCollider)
      this.playerOnFloor = false
      if (result) {
        this.playerOnFloor = result.normal.y > 0
        if (!this.playerOnFloor) {
          this.playerVelocity.addScaledVector(
            result.normal,
            -result.normal.dot(this.playerVelocity)
          )
        }
        this.playerCollider.translate(
          result.normal.multiplyScalar(result.depth)
        )
      }
    },
 
    getForwardVector() {
      this.camera.getWorldDirection(this.playerDirection)
      this.playerDirection.y = 0
      this.playerDirection.normalize()
      return this.playerDirection
    },
    getSideVector() {
      this.camera.getWorldDirection(this.playerDirection)
      this.playerDirection.y = 0
      this.playerDirection.normalize()
      this.playerDirection.cross(this.camera.up)
      return this.playerDirection
    },
 
teleportPlayerIfOob() {

    if(!(this.player instanceof THREE.Object3D))return
    if (this.player.position.y <= - 25) {

        this.playerCollider.start.set(0, 0.35, 0);
        this.playerCollider.end.set(0, 1, 0);
        this.playerCollider.radius = 0.35;
        this.player.position.copy(new THREE.Vector3().subVectors(this.playerCollider.start,this.playerFixVector));
        this.player.rotation.set(0, 0, 0);

    }

},
    gameUpdate(deltaTime) { 
        // 控制
    this.controls( deltaTime );
    // 更新位置
    this.updatePlayer( deltaTime );
    // 复位检测
    this.teleportPlayerIfOob();
      },
    updatePlayer(deltaTime) {
    if(!(this.player instanceof THREE.Object3D))return

    let speedRatio = 1.5
    let damping = Math.exp(- 20 * deltaTime) - 1; // 阻尼减速

    if (!this.playerOnFloor) {

        this.playerVelocity.y -= this.GRAVITY * deltaTime;
        // small air resistance
        damping *= 0.1;
        speedRatio = 2
    }

    this.playerVelocity.addScaledVector(this.playerVelocity, damping);

    // console.log(playerVelocity)

    // console.log(playerActionState)
    // 前进
    if(this.playerActionState.forward > 0){
        if(this.playerActionState.turn!=0){
            this.player.rotation.y -= this.playerActionState.turn * deltaTime * 2
        }
        // 前进状态持续2s以上转为跑步状态
        if(this.ForwardHoldTimeClock.getElapsedTime()>2){
            if(this.playerOnFloor)speedRatio = 4
        
        }
    }
  
    // 原地转向
    if(this.playerActionState.forward == 0 && this.playerActionState.turn!=0){
       
        this.player.rotation.y -= this.playerActionState.turn * deltaTime * 2
    }
    // 休息状态
   

    const deltaPosition = this.playerVelocity.clone().multiplyScalar(deltaTime * speedRatio); // 速度*时间 = 移动距离 (向量)
    deltaPosition.y /= speedRatio // 速度系数不对高度分量产生效果
    this.playerCollider.translate(deltaPosition);

    this.playerCollisions();

    this.player.position.copy(new THREE.Vector3().subVectors(this.playerCollider.start,this.playerFixVector)); // 更新角色位置，辅以修正向量角色触地

      }
    
    }
};